package com.lsh.ofc.provider.service;

import com.alibaba.dubbo.config.annotation.Service;
import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import com.lsh.base.common.exception.BusinessException;
import com.lsh.base.common.model.CommonResult;
import com.lsh.ofc.api.dto.ReturnDetailDTO;
import com.lsh.ofc.api.dto.ReturnHeadDTO;
import com.lsh.ofc.api.dto.WumartReturnDetailDTO;
import com.lsh.ofc.api.dto.WumartReturnHeadDTO;
import com.lsh.ofc.api.service.ReturnRpcService;
import com.lsh.ofc.core.constant.Constants;
import com.lsh.ofc.core.entity.*;
import com.lsh.ofc.core.enums.RoStatus;
import com.lsh.ofc.core.exception.EC;
import com.lsh.ofc.core.service.OfcBillService;
import com.lsh.ofc.core.service.OfcRoCreateService;
import com.lsh.ofc.core.service.OfcRoService;
import com.lsh.ofc.core.service.OfcSoService;
import org.apache.commons.lang.ObjectUtils;
import org.apache.commons.lang3.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.util.CollectionUtils;

import javax.ws.rs.QueryParam;
import java.math.BigDecimal;
import java.util.*;

/**
 * @author peter
 */
@Service(protocol = "dubbo", validation = "true", timeout = 10000)
public class ReturnRpcServiceImpl implements ReturnRpcService {

    private final Logger logger = LoggerFactory.getLogger(ReturnRpcServiceImpl.class);

    @Autowired
    private OfcRoService ofcRoService;

    @Autowired
    private OfcSoService ofcSoService;

    @Autowired
    private OfcRoCreateService ofcRoCreateService;

    @Autowired
    private OfcBillService ofcBillService;

    @Override
    public CommonResult<List<String>> createRo(ReturnHeadDTO dto) throws BusinessException {
        OfcSoHead soFilter = new OfcSoHead();
        soFilter.setOrderCode(dto.getOrderCode());
        List<OfcSoHead> soHeadList = ofcSoService.findList(soFilter,false);
        if(CollectionUtils.isEmpty(soHeadList)){
            CommonResult.error("so 信息不存在");
        }

        OfcSoHead soHead = soHeadList.get(0);

        dto.setVenderId(soHead.getVenderId());
        logger.info(" 返仓单提交信息 {}", JSON.toJSONString(dto));
        Long returnCode = dto.getReturnCode();
        OfcRoHead filter = new OfcRoHead();
        filter.setReturnCode(returnCode);
        List<OfcRoHead> ros = this.ofcRoService.findList(filter, false);
        if (CollectionUtils.isEmpty(ros)) {
            BigDecimal totalSkuQty = BigDecimal.ZERO;
            List<OfcReturnDetail> details = new ArrayList<>();
            for (ReturnDetailDTO item : dto.getDetails()) {
                BigDecimal skuQty = item.getSkuQty();
                OfcReturnDetail detail = new OfcReturnDetail();
                detail.setReturnCode(returnCode);
                detail.setGoodsCode(item.getGoodsCode());
                detail.setGoodsName(item.getGoodsName());
                detail.setGoodsSaleUnit(item.getGoodsSaleUnit());
                detail.setGoodsPrice(item.getGoodsPrice());
                detail.setGoodsQty(item.getGoodsQty());
                detail.setGoodsAmount(item.getGoodsAmount());
                detail.setSkuCode(item.getSkuCode());
                detail.setSkuQty(skuQty);
                detail.setVenderId(dto.getVenderId());
                details.add(detail);
                totalSkuQty = totalSkuQty.add(skuQty);
            }
            JSONObject ext = new JSONObject();
            ext.put(Constants.RETURN_H_BATCH, dto.getCount());
            ext.put(Constants.RETURN_ORDER_TYPE, dto.getReturnOrderType());
            OfcReturnHead head = new OfcReturnHead();
            head.setOrderCode(dto.getOrderCode());
            head.setReturnCode(dto.getReturnCode());
            head.setRegionCode(dto.getRegionCode());
            head.setAddressCode(dto.getAddressCode());
            head.setOrderAmount(dto.getOrderAmount());
            head.setOrderTime(dto.getCreateTime());
            head.setWarehouseCode(dto.getWarehouseCode());
            head.setWarehouseName(dto.getWarehouseName());
            head.setTotalSkuReturnQty(totalSkuQty);
            head.setExt(ext.toJSONString());
            head.setVenderId(dto.getVenderId());
            head.setDetails(details);
            try {
                ros = this.ofcRoCreateService.prepare(head);
            } catch (BusinessException e) {
                if (EC.SO_OBD_NOT_EXIST.getCode().equals(e.getCode())) {
                    String ret = this.ofcBillService.createBill4Return(head);
                    if (ret == null) {
                        CommonResult.error("已经创建两笔退货单");
                    }
                    return CommonResult.success(Collections.singletonList(ret));
                } else {
                    throw e;
                }
            }
        }
        List<String> billCodes = new ArrayList<>(ros.size());
        for (OfcRoHead ro : ros) {
            billCodes.add(ro.getRoBillCode());
        }

        return CommonResult.success(billCodes);
    }

    @Override
    public CommonResult<Object> queryRoStatus(@QueryParam("returnCode") Long returnCode) throws BusinessException {
        OfcRoHead filter = new OfcRoHead();
        filter.setReturnCode(returnCode);
        List<OfcRoHead> roList = this.ofcRoService.findList(filter, false);
        if (CollectionUtils.isEmpty(roList)) {
            Map<String, Integer> ret = this.ofcBillService.queryReturnStatus(returnCode);
            JSONObject data = new JSONObject();
            data.put("returnCode", returnCode);
            data.put("roCodes", ret.keySet());
            JSONArray ros = new JSONArray();
            for (Map.Entry<String, Integer> entry : ret.entrySet()) {
                String roCode = entry.getKey();
                Integer roStatus = entry.getValue();
                JSONObject obj = new JSONObject();
                obj.put("billCode", roCode);
                obj.put("roCode", roCode);
                obj.put("roStatus", roStatus);
                data.put("status", roStatus);
                ros.add(obj);
            }
            data.put("ros", ros);
            return CommonResult.success((Object) data);
        }

        Set<Integer> roStatusSet = new HashSet<>();
        JSONArray roCodes = new JSONArray();
        JSONArray ros = new JSONArray();
        for (OfcRoHead ro : roList) {
            String roCode = ObjectUtils.toString(ro.getRoCode());
            if (!roCode.isEmpty()) {
                roCodes.add(roCode);
            }
            Integer roStatus = ro.getRoStatus();
            if (RoStatus.CREATED.getValue().equals(roStatus)) {
                try {
                    logger.info(returnCode + " returnCode 查询第三方状态");
                    roStatus = this.ofcRoService.refreshRoStatus(ro);
                } catch (BusinessException e) {
                }
            }
            JSONObject obj = new JSONObject();
            obj.put("billCode", ro.getRoBillCode());
            obj.put("roStatus", roStatus);
            obj.put("roCode", roCode);
            ros.add(obj);
            roStatusSet.add(roStatus);
        }
        //15-提交中；20-提交成功；25-提交失败；30-返仓完成
        int status = RoStatus.COMPLETED.getValue();
        roStatusSet.remove(RoStatus.IGNORED.getValue());
        if (!roStatusSet.isEmpty()) {
            List<Integer> list = new ArrayList<>(roStatusSet);
            Collections.sort(list);
            status = list.get(0);
            if (status < RoStatus.CREATED.getValue().intValue()) {
                //15-提交中
                status = RoStatus.CREATING.getValue();
            } else if (status == RoStatus.CREATE_FAIL.getValue().intValue()) {
                //25-提交失败
                status = RoStatus.CREATE_FAIL.getValue();
            } else if (status == RoStatus.COMPLETED.getValue().intValue()) {
                //30-返仓完成
                status = RoStatus.COMPLETED.getValue();
            } else {
                status = RoStatus.CREATED.getValue();
            }
        }
        JSONObject data = new JSONObject();
        data.put("returnCode", returnCode);
        data.put("roCodes", roCodes);
        data.put("status", status);
        data.put("ros", ros);
        return CommonResult.success((Object) data);
    }

    /**
     * @param roBillCode
     * @return
     * @throws BusinessException
     */
    public String querySoDcFromRo(String roBillCode) throws BusinessException {

        String realSupplierDc = null;
        try {
            OfcRoHead roFilter = new OfcRoHead();
            roFilter.setRoBillCode(roBillCode);
            OfcRoHead roHead = ofcRoService.findOne(roFilter, false);
            if (null == roHead) {
                return null;
            }

            realSupplierDc = querySoDcFromSo(roHead.getSoBillCode());
        } catch (Exception e) {
            logger.error(roBillCode + " ：查询rso DC信息异常", e);
        }

        return realSupplierDc;
    }

    public String querySoDcFromSo(String soBillCode) throws BusinessException {

        String realSupplierDc = null;
        try {

            OfcSoHead soFilter = new OfcSoHead();
            soFilter.setSoBillCode(soBillCode);
            OfcSoHead soHead = ofcSoService.findOne(soFilter, false);
            if (null == soHead) {
                return null;
            }
            JSONObject soExt = JSON.parseObject(soHead.getExt());
            if (null == soExt) {
                return null;
            }
            realSupplierDc = soExt.getString("supplier_code");
            if (StringUtils.isBlank(realSupplierDc)) {
                realSupplierDc = soHead.getSupplierDc();
            }
        } catch (Exception e) {
            logger.error(soBillCode + " ：查询so DC信息异常", e);
        }

        return realSupplierDc;
    }

    @Override
    public CommonResult<List<String>> createWumartRo(WumartReturnHeadDTO dto) throws BusinessException {
        logger.info("物美提总商品，返仓物美，参数：{}", JSON.toJSONString(dto));
        String poCode = dto.getPoCode();
        try {
            OfcSoHead soFilter = new OfcSoHead();
            soFilter.setSoCode(dto.getPoCode());
            soFilter.setValid(1);
            OfcSoHead ofcSoHead = ofcSoService.findOne(soFilter, true);
            if (ofcSoHead == null) {
                throw EC.SO_ORDER_NOT_EXIST.exception("wmPoCode：" + poCode);
            }

            OfcRoHead roFilter = new OfcRoHead();
//            roFilter.setAddressCode(ofcSoHead.getAddressCode());
            roFilter.setOrderCode(ofcSoHead.getOrderCode());
            roFilter.setValid(Integer.valueOf(1));
            int count = ofcRoService.count(roFilter);

            ReturnHeadDTO returnHeadDTO = this.buildCreateRoParam(dto, ofcSoHead);
            returnHeadDTO.setCount(count);
            return this.createRo(returnHeadDTO);
        } catch (BusinessException e) {
            logger.error("创建物美返仓单，系统异常！wmPoCode:" + poCode, e);
            throw e;
        } catch (Exception e) {
            logger.error("创建物美返仓单，系统异常！wmPoCode:" + poCode, e);
            throw EC.ERROR.exception(e.getMessage());
        }
    }

    /**
     * 构建ReturnHeadDTO
     *
     * @param dto
     * @param so
     * @return
     */
    private ReturnHeadDTO buildCreateRoParam(WumartReturnHeadDTO dto, OfcSoHead so) {
        Map<String, OfcSoDetail> supplyCodeSoDetailMap = new HashMap<>((int) (dto.getDetails().size() / 0.75) + 1);
        for (OfcSoDetail detail : so.getDetails()) {
            supplyCodeSoDetailMap.put(detail.getSkuSupplyCode(), detail);
        }

        BigDecimal totalRoAmount = BigDecimal.ZERO;
        List<ReturnDetailDTO> details = new ArrayList<>(dto.getDetails().size());
        for (WumartReturnDetailDTO detailDTO : dto.getDetails()) {
            String skuSupplyCode = detailDTO.getSkuSupplyCode();
            OfcSoDetail soDetail = supplyCodeSoDetailMap.get(skuSupplyCode);
            if (soDetail == null) {
                throw EC.GOODS_IS_ERROR.exception("查询不到该商品对应SO明细，skuSupplyCode:" + skuSupplyCode);
            }

            JSONObject obdDetailExt = JSON.parseObject(soDetail.getExt());
            String priceStr = obdDetailExt.getString(Constants.OFC_SO_WUMART_CALLBACK_SUPPLY_PRICE);
            if (StringUtils.isBlank(priceStr)) {
                throw EC.GOODS_IS_ERROR.exception("商品价格不存在，【" + skuSupplyCode + "】 price：" + priceStr);
            }
            BigDecimal price = new BigDecimal(priceStr);
            BigDecimal goodsAmount = price.multiply(detailDTO.getQty());
            totalRoAmount = totalRoAmount.add(goodsAmount);

            ReturnDetailDTO detail = new ReturnDetailDTO();
            detail.setDetailId(null);
            detail.setSkuCode(soDetail.getSkuCode());
            detail.setGoodsCode(soDetail.getGoodsCode());
            detail.setGoodsName(soDetail.getGoodsName());
            detail.setGoodsSaleUnit(soDetail.getGoodsSaleUnit());

            detail.setSkuQty(detailDTO.getQty());
            detail.setGoodsQty(detailDTO.getQty().divide(soDetail.getGoodsSaleUnit(), 2, BigDecimal.ROUND_HALF_UP));
            detail.setGoodsPrice(price.multiply(soDetail.getGoodsSaleUnit()).setScale(4, BigDecimal.ROUND_HALF_UP));
            detail.setGoodsAmount(goodsAmount);

            details.add(detail);
        }

        ReturnHeadDTO returnHeadDTO = new ReturnHeadDTO();
        returnHeadDTO.setCreateTime(dto.getCreateTime());
        returnHeadDTO.setReturnCode(dto.getRpoCode());
        returnHeadDTO.setOrderAmount(totalRoAmount);

        returnHeadDTO.setAddressCode(so.getAddressCode());
        returnHeadDTO.setOrderCode(so.getOrderCode());
        returnHeadDTO.setRegionCode(so.getRegionCode());
        returnHeadDTO.setWarehouseCode(so.getWarehouseCode());
        returnHeadDTO.setWarehouseName(so.getWarehouseName());
        returnHeadDTO.setDetails(details);

        return returnHeadDTO;
    }
}
